﻿using Common.Utils;
using Newtonsoft.Json;
using ReactiveUI.Fody.Helpers;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Common.ViewModels
{
    /// <summary>
    /// 虚拟移动体
    /// </summary>
    [Serializable]
    [JsonObject(MemberSerialization.OptIn)]
    public class VisualMoveCollector : ViewModelBase
    {
        /// <summary>
        /// 移动被移动的物体
        /// </summary>
        public IPosition MoveBase { get; set; }

        private readonly object m_LockBoatMoveState = new object();

        [Reactive] public CarStatus CarStatus { get; set; } = CarStatus.Unknow;

        [Reactive] public double InterruptPos { get; set; }

        [Reactive] public bool HaveInterruptPos { get; set; }

        public virtual void CmdMoveAbsAsync(double pos, int speed, out string error)
        {
            error = "";
            Task.Run(() =>
            {
                try
                {
                    HaveInterruptPos = false;
                    //if (this.MoveBase is Car car)
                    //{
                    //    car.Status = CarStatus.Moving;
                    //}
                    this.CarStatus = CarStatus.Moving;
                    int sleepTime = 10;
                    double distance = pos - MoveBase.Position;
                    //此处在这个位置不再移动
                    if (distance == 0)
                    {
                        return;
                    }
                    while (true)
                    {

                        DateTime startTime = DateTime.Now;
                        Thread.Sleep(sleepTime);
                        TimeSpan timeSpan = DateTime.Now - startTime;

                        double offset = timeSpan.TotalMilliseconds * speed * 0.001;
                        if (distance < 0)
                        {
                            offset = -offset;
                        }

                        double currentValue = this.MoveBase.Position + offset;
                        if (distance >= 0)
                        {
                            if (currentValue >= pos)
                            {
                                currentValue = pos;
                                break;
                            }
                        }
                        else
                        {
                            if (currentValue <= pos)
                            {
                                currentValue = pos;
                                break;
                            }
                        }
                        this.MoveBase.Position = currentValue;
                    }
                    this.MoveBase.Position = pos;
                }
                catch (Exception E)
                {

                }
                finally
                {
                    this.CarStatus = CarStatus.Stopped;
                    //变更完成信号
                }

            });
        }

        public virtual void CmdMoveAbs(double pos, int speed, out string error)
        {
            error = "";
            try
            {
                HaveInterruptPos = false;
                this.CarStatus = CarStatus.Moving;
                int sleepTime = 10;
                double distance = pos - MoveBase.Position;
                //此处在这个位置不再移动
                if (distance == 0)
                {
                    return;
                }
                while (true)
                {
                   

                    DateTime startTime = DateTime.Now;
                    Thread.Sleep(sleepTime);
                    TimeSpan timeSpan = DateTime.Now - startTime;

                    double offset = timeSpan.TotalMilliseconds * speed * 0.001;
                    if (distance < 0)
                    {
                        offset = -offset;
                    }

                    double currentValue = this.MoveBase.Position + offset;
                    if (distance >= 0)
                    {
                        if (currentValue >= pos)
                        {
                            currentValue = pos;
                            break;
                        }
                    }
                    else
                    {
                        if (currentValue <= pos)
                        {
                            currentValue = pos;
                            break;
                        }
                    }
                    this.MoveBase.Position = currentValue;
                }
                this.MoveBase.Position = pos;
            }
            catch (Exception E)
            {

            }
            finally
            {
                this.CarStatus = CarStatus.Stopped;
                //变更完成信号
            }
        }

        /// <summary>
        /// 移动并等待完成信号
        /// </summary>
        /// <param name="pos">位置</param>
        /// <param name="speed">速度</param>
        /// <param name="error"></param>
        public virtual void MoveAndWaitComplete(double pos, int speed, out string error)
        {
            error = "";
            bool isMoveComplete = false;
            var dispose = this.WhenAnyValue(x => x.CarStatus).Skip(1).Subscribe((state) =>
            {
                if (state == CarStatus.InPos)
                {
                    isMoveComplete = true;
                }
            });
            CmdMoveAbsAsync(pos, speed, out error);
            //todo 岳志峰  等待移动完成(初始状态是移动中,这里在实际生产中闭环控制 容易出现疏漏,当运动时间小于读取周期时,将会出现移动完成失败 )
            while (true)
            {
                // 假设变更的一瞬间就Stop了,此处判断周期问题解决(待解决) 先检测Moving,后检测Stop
                if (isMoveComplete)
                {
                    dispose.Dispose();
                    break;
                }

                Thread.Sleep(100);
            }
        }

        /// <summary>


        public static void DealMoveBefore(Station fromStation, Station endStation, BoatVM car)
        {
           

            //LogHelp.AddLog<FtpCarLog>(new FtpCarLog($"开始从站点{fromStation.Name} 移动至站点{endStation.Name}"){CarName = car.Name});
        }

        public static void DealMoveAfter(Station fromStation, Station endStation, BoatVM car)
        {
            //从主通道带着小车进入到工作通道,需要释放小车
            if (fromStation.是否主通道站点 && (!endStation.是否主通道站点) && car.CurrentCar != null)
            {
                //ProductLine.Instance.主通道调度.Realse();
            }

            //LogHelp.AddLog<FtpCarLog>(new FtpCarLog($"开始从站点{fromStation.Name} 移动至站点{endStation.Name}"){CarName = car.Name});
        }


        public VisualMoveCollector(IPosition moveBase)
        {
            MoveBase = moveBase;

            this.WhenAnyValue(x => x.CarStatus).Subscribe(x =>
            {
                if (MoveBase is Car car)
                {
                    car.Status = x;
                }

                if (MoveBase is Axis axis)
                {
                    axis.Status = x;
                }
            });

        }
    }
}
